package com.example.demo.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import static com.example.demo.constant.ApplicationConstant.*;
import static com.example.demo.constant.ApplicationConstant.FILE_TYPE;

/**
 * 监听文件的变化
 */

@Slf4j
public class FileListenAdaptor extends FileAlterationListenerAdaptor {

    /**
     * class 文件变化时重新加载
     */
    @Override
    public void onFileChange(File file) {
        log.info("file change: {}", file.toURI().getPath());
        doServer(file);
        super.onFileChange(file);
        try{
            InputStream is = new FileInputStream(file);
            log.info("file length: {}", is.available());
        }catch (Exception e){

        }
    }

    @Override
    public void onFileCreate(File file) {
        log.info("onFileCreate: {}", file.toURI().getPath());
        super.onFileCreate(file);
        doServer(file);
    }

    @Override
    public void onFileDelete(File file) {
        log.info("onFileDelete: {}", file.toURI().getPath());
        super.onFileDelete(file);
    }

    @Override
    public void onStart(FileAlterationObserver observer) {
        super.onStart(observer);
    }

    private void doServer(File f) {
        if (f.getName().endsWith(FILE_TYPE)) {
            //类文件路径换成类的全限定名
            String path = f.toURI().getPath();
            //文件在class path的路径
            MyClassLoader loader = new MyClassLoader();
            String clazzStr = path.substring(loader.getClassPath().length());
            String className = clazzStr.replaceAll(LINUX_SEQ, PACK_SEQ).substring(0, clazzStr.lastIndexOf(FILE_TYPE));

            try {
                //reload class
                log.info("Reload class for name: {}", className);
                Class<?> clazz = new MyClassLoader().loadClass(className);
                if (className.contains("HotSwap")){
                    Object obj = clazz.getConstructor().newInstance();
                    clazz.getMethod("sayHello").invoke(obj);
                }
            } catch (Exception e) {
                log.info("Reload class error", e);
            }
        }
    }
}
